﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using HWEngine;

namespace HandWriter
{
	public class LinesPointsSelectController
	{
		private Random _rand = new Random();
		private Letter Letter { get; set; }
		public int PointIndex { get; private set; }
		public int LineIndex { get; private set; }

		public LinesPointsSelectController(Letter l)
		{
			Letter = l;
			LineIndex = -1;
			PointIndex = -1;
		}

		public bool IsLineSelected
		{
			get
			{
				if (LineIndex >= 0 && LineIndex < Letter.Lines.Count)
				{
					return true;
				}
				LineIndex = -1;
				return false;
			}
		}

		public bool IsPointSelected
		{
			get
			{
				if (IsLineSelected && PointIndex >= 0 && PointIndex < SelectedLine.Points.Count)
				{
					return true;
				}
				PointIndex = -1;
				return false;
			}
		}

		public Line SelectedLine
		{
			get 
			{
				return IsLineSelected ? Letter.Lines[LineIndex] : null;
			}
		}

		public PointF SelectedPoint
		{
			get
			{
				return SelectedLine.Points[PointIndex];
			}
		}

		public void SetSelection(int lineIndex, int pointIndex)
		{
			LineIndex = lineIndex;
			PointIndex = pointIndex;
		}

		public void UpdateSelectedPoint(PointF pointF)
		{
			SelectedLine.Points[PointIndex] = pointF;

			Letter.ChangedLines = true;
		}

		public void DeleteLine()
		{
			if (IsLineSelected)
			{
				DeleteLine(LineIndex);
			}
		}

		public void DeleteLine(int index)
		{
			Letter.Lines.RemoveAt(index);
			Letter.ChangedLines = true;
				
			LineIndex = LineIndex - 1;
			if (LineIndex < 0 && Letter.Lines.Count > 0)
			{
				LineIndex = 0;
			}
			PointIndex = 0;
		}

		public void DeletePoint()
		{
			if (IsPointSelected)
			{
				DeletePoint(PointIndex);
			}
		}

		public void DeletePoint(int index)
		{
			if (SelectedLine.Points.Count > 2)
			{
				Letter.Lines[LineIndex].RemovePoint(PointIndex);
				Letter.ChangedLines = true;
				PointIndex = PointIndex - 1;
				if (PointIndex < 0 && SelectedLine.Points.Count > 0)
				{
					PointIndex = 0;
				}
			}
		}

		public void AddPoint(Func<PointF?> pointPositioner, int newIndex)
		{
			if (newIndex < 0)
			{
				newIndex = SelectedLine.LastPointIndex;
			}

			if (IsLineSelected)
			{
				if (newIndex == SelectedLine.LastPointIndex)
				{
					//try to automate
					var newPoint = pointPositioner();
					if (newPoint == null)
					{
						//last point
						var li = SelectedLine.LastPointIndex;
						float nX = 2 * SelectedLine.Points[li].X - SelectedLine.Points[li - 1].X;
						float nY = 2 * SelectedLine.Points[li].Y - SelectedLine.Points[li - 1].Y;
						newPoint = new PointF(nX, nY);
					}

					SelectedLine.InsertPoint(newPoint.Value, -1);
				}
				else
				{
					//middle point
					var points = SelectedLine.CalculateSpline().ToArray();
					var c = points.Length / (float)(SelectedLine.Points.Count - 1);
					var c1 = (int)(c * newIndex);
					var c2 = (int)(c * (newIndex + 1));
					SelectedLine.InsertPoint(points[(c2+c1)/2], newIndex + 1);
				}
				Letter.ChangedLines = true;
				PointIndex = PointIndex + 1;
			}
		}

		public void AddLine()
		{
			Line l = new Line();
			int c = Letter.Lines.Count;
			l.Points.Add(new PointF(50 + c * 10 + _rand.Next(50), c * 10 + 150 + _rand.Next(50)));
			l.Points.Add(new PointF(150 + c * 10 + _rand.Next(50), c * 10 + 150 + _rand.Next(50)));
			Letter.Lines.Add(l);
			Letter.ChangedLines = true;

			SetSelection(Letter.Lines.Count - 1, -1);
		}
	}
}
